import {
    _decorator,
    Animation,
    bits,
    Collider2D,
    Component,
    Contact2DType,
    log,
    Node,
    PolygonCollider2D,
    randomRangeInt,
    toDegree,
    toRadian,
    tween,
    EventTarget,
    Vec2,
    UIOpacity,
    AudioClip,
    AudioSource,
    instantiate,
    Vec3,
    ProgressBar
} from 'cc';
import { Battle } from '../Battle';
import { Enum_AudioClip, Enum_ColliderGroup } from '../Enum';
import { Util } from '../Util';
import { Player_Buttle } from './Player_Buttle';
import { Globals } from '../Globals';
import StorageManager from '../Data/StorageManager';
import { getPlayerData } from '../Data/PlayerData';
import { skillType } from '../Data/SkillData';
import { ResourcesUtil } from '../ResourcesUtil';
import { AnimationController } from '../Logic/AnimationController';
import { TreeController } from '../Logic/TreeController';
import { GameAPI } from '../Common/GameAPI';
import { EnEvent } from '../Common/const/EnEvent';
import { EnemyController } from '../Logic/Enemy/EnemyController';
import { SpineRedBlinkEffect } from '../Logic/SpineRedBlinkEffect';
import { PlayerCondroller } from './PlayerCondroller';

const { ccclass, property } = _decorator;

@ccclass('Player')
export class Player extends Component {

    @property(Node)
    private bodyNode: Node = null;
    @property(Node)
    private energyPrefab: Node = null;
    @property(Node)
    private attackEffectNode: Node = null;
    @property(ProgressBar)
    private hpProgress: ProgressBar = null;

    // @property(AudioClip) damageWoman: AudioClip;
    // @property(AudioClip) damageMan: AudioClip;

    private _damageMan: AudioClip;
    private _sword3: AudioClip;
    private _hurt: AudioClip;
    private _die: AudioClip;
    private gunNode: Node = null; //枪节点
    private _playerCollider: Collider2D = null;
    private _onEvent: Function;
    private _target: any;
    private _level = 1; //等级

    // 事件类型
    static readonly Event = {
        HURT: 0,
        DEAD: 1,
        CURE: 2,
    }

    public animController: AnimationController;

    private _audioSound: AudioSource; // 音效
    // 经验值
    private _exp = 0;
    private _maxExp = 100; // 最大经验值,达到这个值升级
    // 技能容器
    private _skillList: Array<skillType> = [];
    public get skillList(): Array<skillType> {
        return this._skillList;
    }
    public set skillList(value: Array<skillType>) {
        this._skillList = value;
    }

    public playerRadian: number = 0;
    public direction: number = 0;

    public isAttacking: boolean = false;
    private isAttackState: boolean = false;
    private isIdle: boolean = false;

    private spineRedBlinkEffect: SpineRedBlinkEffect;

    // 攻击方向
    private _attackDirection: number = 0;
    public get attackDirection(): number {
        return this._attackDirection;
    }
    public set attackDirection(value: number) {
        this._attackDirection = value;
    }

    //最大生命值
    private _maxHp = 1000;

    public get maxHp() {
        return this._maxHp;
    }

    public set maxHp(value) {
        this._maxHp = value;
    }

    // 是否护盾
    private _isShield = false;
    public get isShield() {
        return this._isShield;
    }
    public set isShield(value) {
        this._isShield = value;
    }

    // 生命
    private _hp = 0;

    public get hp() {
        return this._hp;
    }

    public set hp(value) {
        this._hp = value;
        this._hp >= this._maxHp && (this._hp = this._maxHp);
        // 让main节点监听到事件
        this._onEvent && this._onEvent.apply(this._target, [Player.Event.CURE, this._hp]);

    }
    // 攻击速度
    private _attackSpeed = 1;  // 攻击间隔

    // 速度
    private _speed: number = 5;

    // 移动方向
    private _moveDirection: number = 0;
    public get moveDirection(): number {
        return this._moveDirection;
    }

    public set moveDirection(value: number) {
        this._moveDirection = value;
    }


    // 是否移动
    private _isMoveing: boolean = false;
    public get isMoveing(): boolean {
        return this._isMoveing;
    }

    public set isMoveing(value: boolean) {
        this._isMoveing = value;
        // 改变play动画
        // if (this.animController) {
        //     if (this._isMoveing) {
        //         this.animController.UpdateAnim("walk2");
        //     } else {
        //         this.animController.UpdateAnim("stand2");
        //     }
        // }
    }

    async onLoad() {
        // this.isAttacking = true;
        this.animController = this.bodyNode.getChildByName("anim").getComponent(AnimationController);
        this._audioSound = this.node.getComponent(AudioSource);
        // 音频
        this._damageMan = await ResourcesUtil.loadAudioClip(Enum_AudioClip.damage_1_man);
        this._sword3 = await ResourcesUtil.loadAudioClip(Enum_AudioClip.sword3);
        this._hurt = await ResourcesUtil.loadAudioClip(Enum_AudioClip.hurt);
        this._die = await ResourcesUtil.loadAudioClip(Enum_AudioClip.die);
        // this._hp = this._maxHp = getPlayerData(StorageManager.instance.currRole).maxHp || 100; // 初始化生命值
        // this._speed = getPlayerData(StorageManager.instance.currRole).speed || 6; // 初始化速度
        // this._attackSpeed = getPlayerData(StorageManager.instance.currRole).attackSpeed || .5; // 初始化攻击速度
        this._level = 1; // 等级初始化
        this._exp = 0; // 经验值初始化
        this._maxExp = 100; // 最大经验值初始化
        // 把player节点赋值给外面的Battle中的playerNode
        this.node && (Battle.playerNode = this.node);
        this.maxHp = 2500;
        this._hp = this.maxHp;
    }

    async onEnable(): Promise<void> {
        this.spineRedBlinkEffect = this.node.getComponent(SpineRedBlinkEffect);
        // this.gunNode = Globals.getNode("Gun", Battle.playerNode.parent);
        this.isAttacking = false;
        this.isAttackState = false;
    }

    start() {
        // 碰撞监听
        this._playerCollider = this.node.getComponent(PolygonCollider2D);
        if (this._playerCollider) {
            this._playerCollider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
            this._playerCollider.on(Contact2DType.END_CONTACT, this.onEndContact, this);
        }
        // 0.01秒计算一次最近的敌人的弧度
        // this.schedule(() => {
        // if (nearestEnemy) {
        //     // end点 - start点
        //     const y = nearestEnemy.getWorldPosition().y - Battle.playerNode.getWorldPosition().y;
        //     const x = nearestEnemy.getWorldPosition().x - Battle.playerNode.getWorldPosition().x;
        //     this.attackDirection = Math.atan2(y, x); //计算出一个点到另一个点在x轴上的弧度
        // } else {
        //     // 如果血量和最近敌人不存在，就攻击移动的方向
        //     this.attackDirection = this._moveDirection;
        // }
        // }, .01)
    }

    onDisable(): void {
        // 碰撞注销监听
        if (this._playerCollider) {
            this._playerCollider.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
            this._playerCollider.off(Contact2DType.END_CONTACT, this.onEndContact, this);
        }
    }

    AttackLogic() {
        const nearestEnemy = this.getAttackTargets(240);
        if (nearestEnemy && nearestEnemy.length > 0) {
            this.isAttackState = true;
            if (this.isAttacking) {

            }
            else {
                this.isAttacking = true;
                let target = this.getMinDistanceEnemy(nearestEnemy);
                const y = target.getWorldPosition().y - Battle.playerNode.getWorldPosition().y;
                const x = target.getWorldPosition().x - Battle.playerNode.getWorldPosition().x;
                this.attackDirection = Math.atan2(y, x);
                this.attackDirection = this._moveDirection;
                this.animController.UpdateAnim("Attack2", false, 1);
                this._audioSound.playOneShot(this._sword3);
                if (target.getWorldPosition().x >= this.node.getWorldPosition().x) {
                    this.bodyNode.setScale(1, 1);
                } else {
                    this.bodyNode.setScale(-1, 1);
                }
                // this.attackEffectNode.getWorldPosition()
                GameAPI.FireGEvent(EnEvent.CreateEffectEvent, { effectName: "zhujue_attack_effect", position: new Vec3(0, 0, 0), scale: this.bodyNode.scale, parentNode: this.attackEffectNode });
                this.scheduleOnce(function () {
                    this.isAttacking = false;
                }.bind(this), 1);
                for (let index = 0; index < nearestEnemy.length; index++) {
                    const element = nearestEnemy[index];
                    if (element.name.includes("Tree")) {
                        let tree = element.getComponent(TreeController);
                        tree.StartCut();
                    }
                    else {
                        let enemyController = element.getComponent(EnemyController);
                        if (enemyController) {
                            if (enemyController.isBoss) {
                                enemyController.AttackedPlayer();
                            }
                            enemyController.Injured(10);
                        }
                    }
                    GameAPI.FireGEvent(EnEvent.CreateEffectEvent, { effectName: "zhujue_attack_hit", position: element.position, scale: element.scale, parentNode: null });
                }
            }
        }
        // else {
        //     this.isAttacking = false;
        //     this.isAttackState = false;
        // }
    }

    update(deltaTime: number) {
        if (Battle.startGame) {
            this.AttackLogic();
            this.move();
            if (!this.isAttacking && !this._isMoveing && !this.isAttackState) {
                if (!this.isIdle) {
                    this.isIdle = true;
                    this.animController.SetIdle("stand2");
                }
            }
            else {
                this.isIdle = false;
            }
        }
    }

    // 1、注册事件回调函数(保存事件回调函数),下面调用此回调函数
    onPlayerEvent(onEvent: Function, target?: any) {
        this._onEvent = onEvent;
        this._target = target;
    }

    //下一等级所需经验
    private _getNextLevelExp(level: number) {
        if (level <= 20) {
            return 100 + level * 10;
        } else if (level <= 50) {
            return 200 + level * 15;
        } else {
            return level ** 2 + level * 20;
        }
    }

    CreatorRouItem(pos) {
        let obj = instantiate(this.energyPrefab);
        Battle.EnergyObjParent.addChild(obj);
        obj.setPosition(pos);
        obj.active = true;
    }

    // 增加经验
    addExp(exp: number, enemyNode: Node, boss: boolean) {
        this._exp += exp;
        if (this._exp >= this._maxExp) {
            this._exp -= this._maxExp; //多出来的经验值
            this._level++; // 等级提升
            this._maxExp = this._getNextLevelExp(this._level) // 下一等级所需经验
        }
        // 事件发射(添加经验)
        (window as any).GlobalEventTarget.emit("eventAddExp", this._exp, this._maxExp, this._level);
        if (!boss) {
            this.CreatorRouItem(enemyNode.position);
        }
        else {
            this.CreatorRouItem(enemyNode.position);
            let playerPos = enemyNode.position;
            let num: number = 0;
            for (let index = 0; index < 5; index++) {
                let pos = new Vec3();
                num++;
                if (num == 1 || num == 6) {
                    pos = new Vec3(playerPos.x + 10 * num, playerPos.y);
                }
                else if (num == 2 || num == 7) {
                    pos = new Vec3(playerPos.x - 10 * num, playerPos.y);
                }
                else if (num == 3 || num == 8) {
                    pos = new Vec3(playerPos.x, playerPos.y - 10 * num);
                }
                else if (num == 4 || num == 9) {
                    pos = new Vec3(playerPos.x, playerPos.y + 10 * num);
                }
                else if (num == 5 || num == 10) {
                    pos = new Vec3(playerPos.x - 5 * num, playerPos.y + 5 * num);
                }
                this.CreatorRouItem(pos);
            }
        }

    }

    MoveToIdle() {
        this.animController.UpdateAnim("stand2", true, 0);
        this.animController.SetNone();
    }

    // 移动函数
    move() {
        if (this.isMoveing) {
            Util.nodeMove(this.node, this.moveDirection, this._speed);
            const degree = toDegree(this.moveDirection); //把移动弧度转为角度
            // 改变角色方向
            if (degree >= -90 && degree <= 90) {
                this.bodyNode.setScale(1, 1);
            } else {
                this.bodyNode.setScale(-1, 1);
            }
        }
    }

    MoveTargetDirection(value) {
        if (value > 0) {
            this.bodyNode.setScale(1, 1);
        } else {
            this.bodyNode.setScale(-1, 1);
        }
        this.animController.UpdateAnim("walk2", true, 0);
    }

    // 受到伤害
    Injured(hurt: number) {
        if (this.spineRedBlinkEffect) {
            this.spineRedBlinkEffect.startBlink();
        }
        this._hp -= hurt;
        // 播放音效
        this._audioSound.playOneShot(this._damageMan);
        // 伤害数字
        // Util.damageTextFun(`${hurt}`, "00FF47", this.node.getWorldPosition(), Battle.DamageTextParent);
        if (this._hp <= 0) {
            this._hp = 0;
            // 2、注册的事件回调函数，这里调用
            log("玩家死亡");
            // this._onEvent && this._onEvent.apply(this._target, [Player.Event.DEAD, 0]);
            this._audioSound.playOneShot(this._die);
            this.scheduleOnce(function () {
                GameAPI.FireGEvent(EnEvent.GameFailEvent);
            }.bind(this), 1);
            this.hpProgress.node.active = false;
        } else {
            this.hpProgress.progress = this.hp / this.maxHp;
            this._audioSound.playOneShot(this._hurt);
            this._onEvent && this._onEvent.apply(this._target, [Player.Event.HURT, this._hp]);
        }
    }

    // 碰撞开始回调
    onBeginContact(self: Collider2D, other: Collider2D) {
        // 碰到敌人
        if (other.group === Enum_ColliderGroup.ENEMY && !other.node.name.includes("Tree")) {
            // 没有互等就受到伤害
            // !this._isShield && this.Injured(other.getComponent(Enemy).hurt);
            // Globals.putNode(other.node);// 碰撞后销毁敌人
        }
    }

    // 碰撞结束回调
    onEndContact(self: Collider2D, other: Collider2D) {
        log("碰撞结束");
        if (other.group === Enum_ColliderGroup.MAIN_TOWER) {

        }
    }

    /**
     * 创建player玩家子弹(普通攻击)
     *  */
    startCreatePlayerBullet() {
        // 枪的火焰节点
        // const muzzle = this.gunNode.getChildByName("muzzle");
        if (!Battle.EnemyParent.children) {
            tween(this.node).stop();
            return;
        }
        const tw = tween(this.node)
            .delay(this._attackSpeed) //子弹发射间隔
            .call(() => {
                // 火焰显示
                // muzzle.active = true;
            })
            .delay(0.05)
            .call(() => {
                // 枪的火焰
                // muzzle.active = true;
                // 节点对象池拿到子弹
                let angle = toDegree(this._attackDirection);
                const playerBulletNode = Globals.getNode("Player_Bullet", Battle.PlayerBulletParent);
                playerBulletNode.setWorldPosition(this.gunNode.getWorldPosition());//设置子弹初始点
                playerBulletNode.angle = angle; //设置子弹偏移角度，最近敌人的方向
                // 修改子弹节点Player_Buttle组件中的值
                playerBulletNode.getComponent(Player_Buttle).isMoveing = true;
                playerBulletNode.getComponent(Player_Buttle).moveDirection = this._attackDirection;
            })
            .delay(0.1)
            .call(() => {
                // 火焰消失
                // muzzle.active = false;
            })
        // 重复执行tw缓动
        tween(this.node).repeatForever(tw).start();
    }

    /**
    * 攻击最近的敌人（获取最近敌人的方向）
    * @param extent （可选）给定一个距离范围,不填返回最近的敌人
    */
    getAttackTargets(extent?: number) {
        const Enemys = Battle.EnemyParent.children;
        const playerWorldPos = Battle.playerNode.getWorldPosition();
        let attackTargets = 10;
        let targets: Node[] = [];
        for (let i = 0; i < Enemys.length; i++) {
            let enemyNode = Enemys[i];
            let result = false;
            let nodeName = enemyNode.name;
            if (nodeName.includes("Enemy") || nodeName.includes("Boss")) {
                let enemyCom = enemyNode.getComponent(EnemyController);
                if (!enemyCom.isDie) {
                    result = true;
                }
            }
            else if (nodeName.includes("Tree")) {
                let enemyCom = enemyNode.getComponent(TreeController);
                if (!enemyCom.isDie) {
                    result = true;
                }
            }
            if (result) {
                let point = enemyNode.getChildByName("Point");
                if (point == null) {
                    point = enemyNode;
                }
                const distance = Vec2.distance(point.getWorldPosition(), playerWorldPos);
                if (extent && distance <= extent && targets.length <= attackTargets) {
                    // 范围内敌人
                    targets.push(enemyNode);
                }
            }
        }
        return targets;
    }

    /**
     * 最近的敌人（获取最近敌人的方向）
     * @returns 敌人节点
     */
    getMinDistanceEnemy(targets) {
        const playerWorldPos = Battle.playerNode.getWorldPosition();
        let minDistance = bits.INT_MAX; //最近的距离，先赋值一个最大值
        let target: Node = null;
        for (let i = 0; i < targets.length; i++) {
            // 获取距离
            const distance = Vec2.distance(targets[i].getWorldPosition(), playerWorldPos);
            if (distance < minDistance) {
                // 最近敌人
                minDistance = distance; //更新最近的距离
                target = targets[i]; //更新最近的敌人
            }
        }
        return target;
    }

    /**
     * 攻击最近的敌人（获取最近敌人的方向）
     * @param extent （可选）给定一个距离范围,不填返回最近的敌人
     * @returns 敌人节点
     */
    getNearestEnemy(extent?: number) {
        //测试功能先注释敌人的节点获取
        const Enemys = Battle.EnemyParent.children;
        const playerWorldPos = Battle.playerNode.getWorldPosition();
        let minDistance = bits.INT_MAX; //最近的距离，先赋值一个最大值
        let targets: Node[] = [];
        let target: Node = null;
        for (let i = 0; i < Enemys.length; i++) {
            // 获取距离
            const distance = Vec2.distance(Enemys[i].getWorldPosition(), playerWorldPos);
            if (extent && distance <= extent) {
                // 范围内敌人
                targets.push(Enemys[i]);
            } else if (distance < minDistance) {
                // 最近敌人
                minDistance = distance; //更新最近的距离
                target = Enemys[i]; //更新最近的敌人
            }
        }

        let trees = Battle.EnemyTree.children;
        for (let i = 0; i < trees.length; i++) {
            // 获取距离
            const distance = Vec2.distance(trees[i].getWorldPosition(), playerWorldPos);
            if (extent && distance <= extent) {
                // 范围内的树
                targets.push(trees[i]);
            } else if (distance < minDistance) {
                // 最近的树
                minDistance = distance;
                target = trees[i];
            }
        }
        return targets.length > 0 ? targets[randomRangeInt(0, targets.length + 1)] : target;
    }
    /**
     * 攻击血量最少的敌人（获取血量敌人的方向）
     * @param extent  给定一个范围
     * @returns 敌人节点
     */
    getHpMinEnemy(extent: number) {
        const Enemys = Battle.EnemyParent.children;
        const playerWorldPos = Battle.playerNode.getWorldPosition();
        let minHp = bits.INT_MAX; //最近的距离，先赋值一个最大值
        let targets: Node[] = [];
        let target: Node = null;
        for (let i = 0; i < Enemys.length; i++) {
            // 获取和敌人距离
            const distance = Vec2.distance(Enemys[i].getWorldPosition(), playerWorldPos);
            const hp = Enemys[i].getComponent(EnemyController).hp;

            if (extent && distance <= extent) {
                // 范围内敌人
                targets.push(Enemys[i]);
                if (hp < minHp) {
                    // 范围里血量最少的敌人
                    minHp = hp; //更新最少血量
                    target = Enemys[i]; //更新血量最少的敌人
                }
            }
        }

        return target ? target : targets[randomRangeInt(0, targets.length + 1)];
    }





}


